#include <windows.h>
#include "CDXDevice.h"
#include "CReleaseMacro.h"

#include <math.h>
#include <algorithm>
#include <assert.h>


CDXDevice::CDXDevice()
{
	m_pD3D11Device = NULL;
	m_pD3D11DeviceContext = NULL;
	m_pD3D10Device = NULL;
	m_pDXGIFactory1 = NULL;

	m_pD2DFactory = NULL;
	m_pDWriteFactory = NULL;
	m_pWICFactory = NULL;
	
	m_csDeviceContext = new CCritSec();
	_CreateD3DDevice();
}

CDXDevice::~CDXDevice()
{
	SAFE_RELEASE(m_pD3D11Device);
	SAFE_RELEASE(m_pD3D11DeviceContext);
	SAFE_RELEASE(m_pD3D10Device);
	SAFE_RELEASE(m_pDXGIFactory1);

	SAFE_RELEASE(m_pD2DFactory);
	SAFE_RELEASE(m_pDWriteFactory);
	SAFE_RELEASE(m_pWICFactory);
	SAFE_DELETE(m_csDeviceContext);
}
ID3D11Device* CDXDevice::GetD3D11Device()
{
	return m_pD3D11Device;
}
ID3D11DeviceContext* CDXDevice::GetD3D11DeviceContext()
{
	return m_pD3D11DeviceContext;
}

HRESULT CDXDevice::_CreateD3DDevice()
{
	SAFE_RELEASE(m_pD3D11Device);
	SAFE_RELEASE(m_pD3D11DeviceContext);

	HRESULT hr = S_OK;

	D3D_FEATURE_LEVEL  FeatureLevelsRequested[] = 
	{
		D3D_FEATURE_LEVEL_11_0,
		D3D_FEATURE_LEVEL_10_1,
	};
	UINT               numLevelsRequested = 2;
	UINT createDeviceFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;

#ifdef _DEBUG
	createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

	IDXGIAdapter* pAdapter = NULL;
	hr = GetDXGIAdapter(0, &pAdapter);
	if (FAILED(hr))
	{
		return hr;
	}

	if( FAILED (hr = D3D11CreateDevice(pAdapter, 
		D3D_DRIVER_TYPE_UNKNOWN, 
		NULL, 
		createDeviceFlags,
		FeatureLevelsRequested, 
		numLevelsRequested, 
		D3D11_SDK_VERSION, 
		&m_pD3D11Device, 
		&m_FeatureLevelsSupported,
		&m_pD3D11DeviceContext )))
	{
		SAFE_RELEASE(pAdapter);
		return hr;
	}

	return S_OK;
}



HRESULT CDXDevice::GetD2DFactory(ID2D1Factory** ppD2DFactory)
{
	HRESULT hr = S_OK;
	if (m_pD2DFactory == NULL)
	{
		hr = D2D1CreateFactory(
			D2D1_FACTORY_TYPE_MULTI_THREADED,
			&m_pD2DFactory
			);
		if (FAILED(hr))
		{
			return E_FAIL;
		}
	}
	*ppD2DFactory = m_pD2DFactory;
	return S_OK;
}

HRESULT CDXDevice::GetDWriteFactory(IDWriteFactory** ppDWriteFactory)
{
	HRESULT hr = S_OK;
	if (m_pDWriteFactory == NULL)
	{
		hr = hr = DWriteCreateFactory(
			DWRITE_FACTORY_TYPE_SHARED,
			__uuidof(IDWriteFactory),
			reinterpret_cast<IUnknown**>(&m_pDWriteFactory)
			);
		if (FAILED(hr))
		{
			return E_FAIL;
		}
	}
	*ppDWriteFactory = m_pDWriteFactory;
	return S_OK;
}
HRESULT CDXDevice::GetD3D10Device(ID3D10Device** ppDevice)
{
	HRESULT hr = S_OK;
	if (m_pD3D10Device == NULL)
	{
		IDXGIAdapter* pAdapter = NULL;
		hr = GetDXGIAdapter(0, &pAdapter);
		if (FAILED(hr))
			return hr;
		UINT createDeviceFlags =  D3D10_CREATE_DEVICE_BGRA_SUPPORT;
#ifdef _DEBUG
		createDeviceFlags |= D3D10_CREATE_DEVICE_DEBUG;
#endif
		hr = D3D10CreateDevice1(pAdapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, 
			D3D10_FEATURE_LEVEL_10_1, D3D10_1_SDK_VERSION, (ID3D10Device1**)&m_pD3D10Device);
		if (FAILED(hr))
		{
			hr = D3D10CreateDevice(pAdapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, 
				D3D10_SDK_VERSION, &m_pD3D10Device);
			if (FAILED(hr))
				return E_FAIL;
		}
		SAFE_RELEASE(pAdapter);
		if (FAILED(hr))
			return E_FAIL;

		m_pD3D10Device->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
	}
	*ppDevice = m_pD3D10Device;
	return S_OK;
}

HRESULT CDXDevice::GetDXGIFactory(IDXGIFactory1** ppDXGIFactory)
{
	HRESULT hr = S_OK;
	if (m_pDXGIFactory1 == NULL)
	{
		hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)(&m_pDXGIFactory1) );
		if (FAILED(hr))
			return E_FAIL;
	}
	*ppDXGIFactory = m_pDXGIFactory1;
	return S_OK;
}
HRESULT CDXDevice::GetDXGIAdapter(UINT idx, IDXGIAdapter** ppAdapter)
{
	HRESULT hr = S_OK;

	IDXGIFactory1* pFactory = NULL;
	hr = GetDXGIFactory(&pFactory);
	if (FAILED(hr))
		return E_FAIL;

	hr = pFactory->EnumAdapters(idx, ppAdapter);
	return hr;
}

HRESULT CDXDevice::GetWICFactory(IWICImagingFactory** ppWICFactory)
{
	HRESULT hr = S_OK;
	if (m_pWICFactory == NULL)
	{
		hr = CoCreateInstance(
			CLSID_WICImagingFactory,
			NULL,
			CLSCTX_INPROC_SERVER,
			IID_IWICImagingFactory,
			reinterpret_cast<void **>(&m_pWICFactory)
			);
		if (FAILED(hr))
			return hr;
	}
	*ppWICFactory = m_pWICFactory;
	return S_OK;
}

HRESULT CDXDevice::GetWICFmtFromDXGIFmt(DXGI_FORMAT dxgiFmt, GUID* wicFmt)
{
	switch (dxgiFmt)
	{
	case DXGI_FORMAT_R8G8B8A8_TYPELESS:
	case DXGI_FORMAT_R8G8B8A8_UNORM:
	case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
	case DXGI_FORMAT_R8G8B8A8_UINT:
	case DXGI_FORMAT_R8G8B8A8_SNORM:
	case DXGI_FORMAT_R8G8B8A8_SINT:
		*wicFmt = GUID_WICPixelFormat32bppRGBA;
		break;
	case DXGI_FORMAT_B8G8R8A8_TYPELESS:
	case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
	case DXGI_FORMAT_B8G8R8X8_TYPELESS:
	case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
	case DXGI_FORMAT_B8G8R8A8_UNORM:
	case DXGI_FORMAT_B8G8R8X8_UNORM:
		*wicFmt = GUID_WICPixelFormat32bppBGRA;
		break;
	case DXGI_FORMAT_R8_TYPELESS:
	case DXGI_FORMAT_R8_UNORM:
	case DXGI_FORMAT_R8_UINT:
	case DXGI_FORMAT_R8_SNORM:
	case DXGI_FORMAT_R8_SINT:
	case DXGI_FORMAT_A8_UNORM:
		*wicFmt = GUID_WICPixelFormat8bppGray;
		break;
	case DXGI_FORMAT_R32_FLOAT:
		*wicFmt = GUID_WICPixelFormat32bppGrayFloat;
		break;

	case DXGI_FORMAT_R32G32B32A32_TYPELESS:
	case DXGI_FORMAT_R32G32B32A32_FLOAT:
	case DXGI_FORMAT_R32G32B32A32_UINT:
	case DXGI_FORMAT_R32G32B32A32_SINT:
		*wicFmt = GUID_WICPixelFormat128bpp8Channels;
		break;
	default:
		return E_NOTIMPL;
	}
	return S_OK;
}
D3D_FEATURE_LEVEL CDXDevice::GetFeatureLevelSupported()
{
	return m_FeatureLevelsSupported;
}
HRESULT CDXDevice::MakeWindowAssociation(int hwnd, UINT flag)
{
	IDXGIFactory1* pFactory = GetDXGIFactory();
	if (pFactory == NULL)
		return E_FAIL;
	pFactory->MakeWindowAssociation((HWND)hwnd, flag);
	return S_OK;
}
HRESULT CDXDevice::GetDXGIFormatNumBits(DXGI_FORMAT fmt, UINT& nBits)
{
	switch (fmt)
	{
	case DXGI_FORMAT_R32G32B32A32_TYPELESS:
	case DXGI_FORMAT_R32G32B32A32_FLOAT:
	case DXGI_FORMAT_R32G32B32A32_UINT: 
	case DXGI_FORMAT_R32G32B32A32_SINT:
		nBits = 128;
		break;
	case DXGI_FORMAT_R32G32B32_TYPELESS:
	case DXGI_FORMAT_R32G32B32_FLOAT:
	case DXGI_FORMAT_R32G32B32_UINT:
	case DXGI_FORMAT_R32G32B32_SINT: 
		nBits = 96;
		break;
	case DXGI_FORMAT_R16G16B16A16_TYPELESS:
	case DXGI_FORMAT_R16G16B16A16_FLOAT: 
	case DXGI_FORMAT_R16G16B16A16_UNORM: 
	case DXGI_FORMAT_R16G16B16A16_UINT: 
	case DXGI_FORMAT_R16G16B16A16_SNORM:
	case DXGI_FORMAT_R16G16B16A16_SINT:
	case DXGI_FORMAT_R32G32_TYPELESS:  
	case DXGI_FORMAT_R32G32_FLOAT:     
	case DXGI_FORMAT_R32G32_UINT: 
	case DXGI_FORMAT_R32G32_SINT:    
	case DXGI_FORMAT_R32G8X24_TYPELESS: 
	case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: 
	case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: 
	case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: 
		nBits = 64;
		break;
	case DXGI_FORMAT_R10G10B10A2_TYPELESS:  
	case DXGI_FORMAT_R10G10B10A2_UNORM:    
	case DXGI_FORMAT_R10G10B10A2_UINT:   
	case DXGI_FORMAT_R11G11B10_FLOAT:      
	case DXGI_FORMAT_R8G8B8A8_TYPELESS:   
	case DXGI_FORMAT_R8G8B8A8_UNORM:      
	case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: 
	case DXGI_FORMAT_R8G8B8A8_UINT:       
	case DXGI_FORMAT_R8G8B8A8_SNORM:      
	case DXGI_FORMAT_R8G8B8A8_SINT:       
	case DXGI_FORMAT_R16G16_TYPELESS:    
	case DXGI_FORMAT_R16G16_FLOAT:     
	case DXGI_FORMAT_R16G16_UNORM:   
	case DXGI_FORMAT_R16G16_UINT:    
	case DXGI_FORMAT_R16G16_SNORM:    
	case DXGI_FORMAT_R16G16_SINT:    
	case DXGI_FORMAT_R32_TYPELESS:    
	case DXGI_FORMAT_D32_FLOAT:   
	case DXGI_FORMAT_R32_FLOAT:    
	case DXGI_FORMAT_R32_UINT:     
	case DXGI_FORMAT_R32_SINT:      
	case DXGI_FORMAT_R24G8_TYPELESS:   
	case DXGI_FORMAT_D24_UNORM_S8_UINT:  
	case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: 
	case DXGI_FORMAT_X24_TYPELESS_G8_UINT: 
		nBits = 32;
		break;
	case DXGI_FORMAT_R8G8_TYPELESS: 
	case DXGI_FORMAT_R8G8_UNORM:   
	case DXGI_FORMAT_R8G8_UINT:   
	case DXGI_FORMAT_R8G8_SNORM:   
	case DXGI_FORMAT_R8G8_SINT:       
	case DXGI_FORMAT_R16_TYPELESS: 
	case DXGI_FORMAT_R16_FLOAT:    
	case DXGI_FORMAT_D16_UNORM:     
	case DXGI_FORMAT_R16_UNORM:   
	case DXGI_FORMAT_R16_UINT:    
	case DXGI_FORMAT_R16_SNORM:   
	case DXGI_FORMAT_R16_SINT:       
		nBits = 16;
		break;
	case DXGI_FORMAT_R8_TYPELESS:   
	case DXGI_FORMAT_R8_UNORM:      
	case DXGI_FORMAT_R8_UINT:       
	case DXGI_FORMAT_R8_SNORM:     
	case DXGI_FORMAT_R8_SINT:      
	case DXGI_FORMAT_A8_UNORM:       
		nBits = 8;
		break;
	case DXGI_FORMAT_R1_UNORM:  
		nBits = 1;
		break;
	case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:  
	case DXGI_FORMAT_R8G8_B8G8_UNORM: 
	case DXGI_FORMAT_G8R8_G8B8_UNORM: 
		nBits = 32;
		break;
	case DXGI_FORMAT_B5G6R5_UNORM:               
	case DXGI_FORMAT_B5G5R5A1_UNORM:             
		nBits = 16;
		break;
	case DXGI_FORMAT_B8G8R8A8_UNORM:            
	case DXGI_FORMAT_B8G8R8X8_UNORM:             
	case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
	case DXGI_FORMAT_B8G8R8A8_TYPELESS: 
	case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: 
	case DXGI_FORMAT_B8G8R8X8_TYPELESS:  
	case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: 
		nBits = 32;
		break;
	default:
		return E_FAIL;
	}
	return S_OK;
}
HRESULT CDXDevice::GetDXGIFormatNumChannel(DXGI_FORMAT fmt, UINT& nChannel, BOOL& bAvgBits)
{
	bAvgBits = TRUE;
	switch (fmt)
	{
	case DXGI_FORMAT_R32G32B32A32_TYPELESS:
	case DXGI_FORMAT_R32G32B32A32_FLOAT:
	case DXGI_FORMAT_R32G32B32A32_UINT: 
	case DXGI_FORMAT_R32G32B32A32_SINT:
		nChannel = 4;
		break;
	case DXGI_FORMAT_R32G32B32_TYPELESS:
	case DXGI_FORMAT_R32G32B32_FLOAT:
	case DXGI_FORMAT_R32G32B32_UINT:
	case DXGI_FORMAT_R32G32B32_SINT: 
		nChannel = 3;
		break;
	case DXGI_FORMAT_R16G16B16A16_TYPELESS:
	case DXGI_FORMAT_R16G16B16A16_FLOAT: 
	case DXGI_FORMAT_R16G16B16A16_UNORM: 
	case DXGI_FORMAT_R16G16B16A16_UINT: 
	case DXGI_FORMAT_R16G16B16A16_SNORM:
	case DXGI_FORMAT_R16G16B16A16_SINT:
		nChannel = 4;
		break;
	case DXGI_FORMAT_R32G32_TYPELESS:  
	case DXGI_FORMAT_R32G32_FLOAT:     
	case DXGI_FORMAT_R32G32_UINT: 
	case DXGI_FORMAT_R32G32_SINT:    
		nChannel = 2;
		break;
	case DXGI_FORMAT_R32G8X24_TYPELESS:
		nChannel = 3;
		bAvgBits = FALSE;
		break;
	case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: 
	case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: 
	case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: 
		nChannel = 3;
		break;
	case DXGI_FORMAT_R10G10B10A2_TYPELESS:  
	case DXGI_FORMAT_R10G10B10A2_UNORM:    
	case DXGI_FORMAT_R10G10B10A2_UINT:
		nChannel = 4;
		bAvgBits = FALSE;
		break;
	case DXGI_FORMAT_R11G11B10_FLOAT:   
		nChannel = 3;
		bAvgBits = FALSE;
		break;
	case DXGI_FORMAT_R8G8B8A8_TYPELESS:   
	case DXGI_FORMAT_R8G8B8A8_UNORM:      
	case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: 
	case DXGI_FORMAT_R8G8B8A8_UINT:       
	case DXGI_FORMAT_R8G8B8A8_SNORM:      
	case DXGI_FORMAT_R8G8B8A8_SINT:
		nChannel = 4;
		break;
	case DXGI_FORMAT_R16G16_TYPELESS:    
	case DXGI_FORMAT_R16G16_FLOAT:     
	case DXGI_FORMAT_R16G16_UNORM:   
	case DXGI_FORMAT_R16G16_UINT:    
	case DXGI_FORMAT_R16G16_SNORM:    
	case DXGI_FORMAT_R16G16_SINT:    
		nChannel = 2;
		break;
	case DXGI_FORMAT_R32_TYPELESS:    
	case DXGI_FORMAT_D32_FLOAT:   
	case DXGI_FORMAT_R32_FLOAT:    
	case DXGI_FORMAT_R32_UINT:     
	case DXGI_FORMAT_R32_SINT:      
		nChannel = 1;
		break;
	case DXGI_FORMAT_R24G8_TYPELESS:   
		nChannel = 2;
		bAvgBits = FALSE;
		break;
	case DXGI_FORMAT_D24_UNORM_S8_UINT:  
	case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: 
	case DXGI_FORMAT_X24_TYPELESS_G8_UINT: 
		nChannel = 2;
		bAvgBits = FALSE;
		break;
	case DXGI_FORMAT_R8G8_TYPELESS: 
	case DXGI_FORMAT_R8G8_UNORM:   
	case DXGI_FORMAT_R8G8_UINT:   
	case DXGI_FORMAT_R8G8_SNORM:   
	case DXGI_FORMAT_R8G8_SINT:       
		nChannel = 2;
		break;
	case DXGI_FORMAT_R16_TYPELESS: 
	case DXGI_FORMAT_R16_FLOAT:    
	case DXGI_FORMAT_D16_UNORM:     
	case DXGI_FORMAT_R16_UNORM:   
	case DXGI_FORMAT_R16_UINT:    
	case DXGI_FORMAT_R16_SNORM:   
	case DXGI_FORMAT_R16_SINT:       
		nChannel = 1;
		break;
	case DXGI_FORMAT_R8_TYPELESS:   
	case DXGI_FORMAT_R8_UNORM:      
	case DXGI_FORMAT_R8_UINT:       
	case DXGI_FORMAT_R8_SNORM:     
	case DXGI_FORMAT_R8_SINT:      
	case DXGI_FORMAT_A8_UNORM:       
		nChannel = 1;
		break;
	case DXGI_FORMAT_R1_UNORM:  
		nChannel = 1;
		break;
	case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:  
		nChannel = 4;
		bAvgBits = FALSE;
		break;
	case DXGI_FORMAT_R8G8_B8G8_UNORM: 
	case DXGI_FORMAT_G8R8_G8B8_UNORM: 
		nChannel = 4;
		break;
	case DXGI_FORMAT_B5G6R5_UNORM:               
		nChannel = 3;
		bAvgBits = FALSE;
		break;
	case DXGI_FORMAT_B5G5R5A1_UNORM:             
		nChannel = 4;
		bAvgBits = FALSE;
		break;
	case DXGI_FORMAT_B8G8R8A8_UNORM:            
	case DXGI_FORMAT_B8G8R8X8_UNORM:             
		nChannel = 4;
		break;
	case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
		nChannel = 4;
		bAvgBits = FALSE;
		break;
	case DXGI_FORMAT_B8G8R8A8_TYPELESS: 
	case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: 
	case DXGI_FORMAT_B8G8R8X8_TYPELESS:  
	case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: 
		nChannel= 4;
		break;
	default:
		return E_FAIL;
	}

	return S_OK;
}

HRESULT CDXDevice::CreateTextFormat(IDWriteTextFormat ** textFormat, FLOAT fontSize, const WCHAR * fontFamilyName,  IDWriteFontCollection * fontCollection,
									DWRITE_FONT_WEIGHT  fontWeight, DWRITE_FONT_STYLE  fontStyle, DWRITE_FONT_STRETCH  fontStretch,
									const WCHAR * localeName)
{
	HRESULT hr = S_OK;
	IDWriteFactory* pFactory = NULL;
	hr = GetDWriteFactory(&pFactory);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	hr = pFactory->CreateTextFormat(fontFamilyName, fontCollection, fontWeight, fontStyle, fontStretch, fontSize, localeName, textFormat);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	
	return hr;
}
HRESULT CDXDevice::CreateTextLayoutEx(IDWriteTextLayout ** textLayout, const WCHAR * string, UINT32  stringLength,
									FLOAT maxWidth, FLOAT  maxHeight, IDWriteTextFormat * textFormat)
{
	HRESULT hr = S_OK;
	IDWriteFactory* pFactory = NULL;
	hr = GetDWriteFactory(&pFactory);
	if (FAILED(hr))
		return hr;
	return pFactory->CreateTextLayout(string, stringLength, textFormat, maxWidth, maxHeight, textLayout);
}


HRESULT CDXDevice::CreateTextLayout(IDWriteTextLayout ** textLayout, const WCHAR * string, UINT32  stringLength,
								 FLOAT maxWidth, FLOAT  maxHeight, FLOAT fontSize)
{
	HRESULT hr = S_OK;
	IDWriteTextFormat* txtFmt = NULL;
	hr = CreateTextFormat(&txtFmt, fontSize);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	hr = CreateTextLayoutEx(textLayout, string, stringLength, maxWidth, maxHeight, txtFmt);
	SAFE_RELEASE(txtFmt);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	return S_OK;
}
HRESULT CDXDevice::CreateGeometryGroup(D2D1_FILL_MODE fillMode, ID2D1Geometry **geometries, UINT geometriesCount, ID2D1GeometryGroup **geometryGroup)
{
	HRESULT hr = S_OK;
	ID2D1Factory* pFactory = NULL;
	hr = GetD2DFactory(&pFactory);
	if (FAILED(hr))
		return hr;
	return pFactory->CreateGeometryGroup(fillMode, geometries, geometriesCount, geometryGroup);
}
HRESULT CDXDevice::CreateEllipseGeometry( const D2D1_ELLIPSE &ellipse, ID2D1EllipseGeometry **ellipseGeometry)
{
	HRESULT hr = S_OK;
	ID2D1Factory* pFactory = NULL;
	hr = GetD2DFactory(&pFactory);
	if (FAILED(hr))
		return hr;
	return pFactory->CreateEllipseGeometry(ellipse, ellipseGeometry);
}
HRESULT CDXDevice::CreatePathGeometry(ID2D1PathGeometry **pathGeometry)
{
	HRESULT hr = S_OK;
	ID2D1Factory* pFactory = NULL;
	hr = GetD2DFactory(&pFactory);
	if (FAILED(hr))
		return hr;
	return pFactory->CreatePathGeometry(pathGeometry);
}
HRESULT CDXDevice::CreateRectangleGeometry( const D2D1_RECT_F *rectangle, ID2D1RectangleGeometry **rectangleGeometry)
{
	HRESULT hr = S_OK;
	ID2D1Factory* pFactory = NULL;
	hr = GetD2DFactory(&pFactory);
	if (FAILED(hr))
		return hr;
	return pFactory->CreateRectangleGeometry(rectangle, rectangleGeometry);
}
HRESULT CDXDevice::CreateDrawingStateBlock(ID2D1DrawingStateBlock **drawingStateBlock)
{
	HRESULT hr = S_OK;
	ID2D1Factory* pFactory = NULL;
	hr = GetD2DFactory(&pFactory);
	if (FAILED(hr))
		return hr;
	return pFactory->CreateDrawingStateBlock(drawingStateBlock);
}



ID2D1Factory* CDXDevice::GetD2DFactory()
{
	HRESULT hr = S_OK;
	ID2D1Factory* pFactory = NULL;
	hr = GetD2DFactory(&pFactory);
	if (FAILED(hr))
	{
		assert(0);
		return NULL;
	}
	return pFactory;
}
IDWriteFactory* CDXDevice::GetDWriteFactory()
{
	HRESULT hr = S_OK;
	IDWriteFactory* pFactory = NULL;
	hr = GetDWriteFactory(&pFactory);
	if (FAILED(hr))
	{
		assert(0);
		return NULL;
	}
	return pFactory;
}
ID3D10Device* CDXDevice::GetD3D10Device()
{
	HRESULT hr = S_OK;
	ID3D10Device* pDevice= NULL;
	hr = GetD3D10Device(&pDevice);
	if (FAILED(hr))
	{
		assert(0);
		return NULL;
	}
	return pDevice;
}

IDXGIAdapter* CDXDevice::GetDXGIAdapter(UINT idx)
{
	HRESULT hr = S_OK;
	IDXGIAdapter* pAdapter= NULL;
	hr = GetDXGIAdapter(idx, &pAdapter);
	if (FAILED(hr))
	{
		assert(0);
		return NULL;
	}
	return pAdapter;
}
IDXGIFactory1* CDXDevice::GetDXGIFactory()
{
	HRESULT hr = S_OK;
	IDXGIFactory1* pFactory = NULL;
	GetDXGIFactory(&pFactory);
	if (FAILED(hr))
	{
		assert(0);
		return NULL;
	}

	return pFactory;
}

IDWriteTextLayout* CDXDevice::CreateTextLayoutEx(const WCHAR* str, UINT len,
											  FLOAT maxWidth, FLOAT maxHeight, IDWriteTextFormat* textFormat)
{
	HRESULT hr = S_OK;
	IDWriteTextLayout* pLayout = NULL;
	hr = this->CreateTextLayoutEx(&pLayout, str, len, maxWidth, maxHeight, textFormat);
	if (FAILED(hr))
	{
		assert(0);
		return NULL;
	}
	return pLayout;
}
IDWriteTextLayout* CDXDevice::CreateTextLayout(const WCHAR* str, UINT len,
											FLOAT maxWidth, FLOAT  maxHeight, FLOAT fontSize)
{
	HRESULT hr = S_OK;
	IDWriteTextLayout* pLayout = NULL;
	hr = this->CreateTextLayout(&pLayout, str, len, maxWidth, maxHeight, fontSize);
	if (FAILED(hr))
	{
		assert(0);
		return NULL;
	}
	return pLayout;
}
ID2D1EllipseGeometry* CDXDevice::CreateEllipseGeometry( const D2D1_ELLIPSE &ellipse)
{
	HRESULT hr = S_OK;
	ID2D1EllipseGeometry* pGeometry = NULL;
	hr = this->CreateEllipseGeometry(ellipse, &pGeometry);
	if (FAILED(hr))
	{
		assert(0);
		return NULL;
	}
	return pGeometry;
}
ID2D1PathGeometry* CDXDevice::CreatePathGeometry()
{
	HRESULT hr = S_OK;
	ID2D1PathGeometry* pGeometry = NULL;
	hr = this->CreatePathGeometry(&pGeometry);
	if (FAILED(hr))
	{
		assert(0);
		return NULL;
	}
	return pGeometry;
}
ID2D1RectangleGeometry* CDXDevice::CreateRectangleGeometry(D2D1_RECT_F rectangle)
{
	HRESULT hr = S_OK;
	ID2D1RectangleGeometry* pGeometry = NULL;
	hr = this->CreateRectangleGeometry(&rectangle, &pGeometry);
	if (FAILED(hr))
	{
		assert(0);
		return NULL;
	}
	return pGeometry;
}
ID2D1DrawingStateBlock* CDXDevice::CreateDrawingStateBlock()
{
	HRESULT hr = S_OK;
	ID2D1DrawingStateBlock* pStateBlock = NULL;
	hr = this->CreateDrawingStateBlock(&pStateBlock);
	if (FAILED(hr))
	{
		assert(0);
		return NULL;
	}
	return pStateBlock;
}























CDXBase::CDXBase(CDXDevice* pDevice)
{
	if (pDevice == NULL)
	{
		assert(0);
		return;
	}
	m_pDevice = pDevice;
	SAFE_ADDREF(m_pDevice);
}
CDXBase::~CDXBase()
{
	SAFE_RELEASE(m_pDevice);
}

BOOL CDXBase::IsSameDevice(const CDXBase* pOther) const
{
	ID3D11Device* pDX11Device = m_pDevice->GetD3D11Device();
	ID3D11DeviceContext* pDX11Context = m_pDevice->GetD3D11DeviceContext();
	
	ID3D11Device* pDX11Device_other = pOther->m_pDevice->GetD3D11Device();
	ID3D11DeviceContext* pDX11Context_other = pOther->m_pDevice->GetD3D11DeviceContext();
	return (pDX11Device == pDX11Device_other) && (pDX11Context == pDX11Context_other);
}	

